home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / Apps / ArchiveUtils / Freeze / ProcessControl.m < prev    next >
Encoding:
Text File  |  1992-12-20  |  6.8 KB  |  289 lines

  1.  
  2. /*
  3.  *    Filename:    ProcessControl.m 
  4.  *    Created :    Sat Dec 21 00:23:34 1991 
  5.  *    Author  :    Vince DeMarco
  6.  *        <vince@whatnxt.cuc.ab.ca>
  7.  */
  8.  
  9.  
  10. /* Generated by Interface Builder */
  11.  
  12. #import "ProcessControl.h"
  13.  
  14. #import <appkit/nextstd.h>
  15.  
  16. #import <appkit/Window.h>
  17. #import <appkit/Panel.h>
  18. #import <appkit/NXBrowser.h>
  19. #import <appkit/NXBrowserCell.h>
  20. #import <appkit/Application.h>
  21. #import <appkit/TextField.h>
  22. #import <appkit/defaults.h>
  23.  
  24. #import <sys/types.h>
  25. #import <sys/stat.h>
  26. #import <sys/dir.h>
  27. #import <sys/file.h>
  28. #import <libc.h>
  29.  
  30. #import "thread.h"
  31. #import "CircularSlider.h"
  32. #import "Freeze.h"
  33. #import "basename.h"
  34. #import "dirname.h"
  35.  
  36. #if !defined(S_ISDIR) && defined(S_IFDIR)
  37. #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
  38. #endif
  39.  
  40. #if !defined(S_ISREG) && defined(S_IFREG)
  41. #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
  42. #endif
  43.  
  44. int is_not_dot_or_dotdot (char *name);
  45.  
  46.  
  47. @implementation ProcessControl
  48.  
  49.  
  50.  
  51. void updateTimer(DPSTimedEntry teNumber, double now, char *userData)
  52. {
  53.     [(id)userData update:(id)userData];
  54. }
  55.  
  56. - init
  57. {
  58.     self = [super init];
  59.     updatetime = atof((char *)NXGetDefaultValue("Freeze","UpdateTime"));
  60.  
  61.     bzero(buffer.buf,BUFFER_SIZE*BUFFER_WIDTH);
  62.     buffer_count = buffer.end = buffer.start = buffer.count = 0;
  63.  
  64.     mutex_init(&buffer.lock);
  65.     mutex_set_name(&buffer.lock,"Buffer Mutex Lock");
  66.  
  67.     condition_init(&buffer.not_empty);
  68.     condition_set_name(&buffer.not_empty,"Buffer not Empty");
  69.  
  70.     condition_init(&buffer.not_full);
  71.     condition_set_name(&buffer.not_full,"Buffer not Full");
  72.  
  73.     /* Start up background thread */
  74.     consumer_thread = cthread_fork(consumer,(any_t)(&buffer)); /* Done like this so it is possible
  75.                                 * to change the priority of the
  76.                                 * background thread easily 
  77.                                 * This also allows you to terminate
  78.                                 * the thread, because now the thread
  79.                                 * descriptor
  80.                                 */
  81.     cthread_set_name(consumer_thread, "Consumer Process");     
  82.     cthread_detach(consumer_thread); 
  83.  
  84.     [NXApp loadNibSection:"Process.nib" owner:self withNames:NO fromZone:[self zone]];
  85.     [window setMiniwindowIcon:"FreezeProcs"];
  86.  
  87.     updateTimedEntry = DPSAddTimedEntry(updatetime, updateTimer,(void *)self, NX_RUNMODALTHRESHOLD);
  88.  
  89.     return self;
  90. }
  91.  
  92. - free
  93. {
  94.     DPSRemoveTimedEntry(updateTimedEntry);
  95.     return [super free];
  96. }
  97.  
  98. - setupdateTime:(double)value
  99. {
  100.     updatetime = value;
  101.     DPSRemoveTimedEntry(updateTimedEntry);
  102.     updateTimedEntry = DPSAddTimedEntry(updatetime, updateTimer,(void *)self, NX_RUNMODALTHRESHOLD);
  103.     return self;
  104. }
  105.  
  106. - (double)updateTime
  107. {
  108.     return updatetime;
  109. }
  110.  
  111. - displayProcesses:sender
  112. {
  113.     [window makeKeyAndOrderFront:sender];
  114.     return self;
  115. }
  116.  
  117. - addFile:(char *)filename
  118. {
  119.     char *directory;
  120.     struct stat stats;
  121.  
  122.     if (access(filename,R_OK|F_OK) < 0){
  123.     NXRunAlertPanel("Can't Process File",
  124.             "You don't have read access to file %s",
  125.             "Okay",NULL,NULL,filename);
  126.     return self;
  127.     }
  128.     if (access(directory = dirname(filename),W_OK) < 0){
  129.     NXRunAlertPanel("Can't Process File",
  130.             "Can't process file %s because you do not have write access to directory %s",
  131.             "Okay",NULL,NULL,basename(filename),directory);
  132.     return self;
  133.     }    
  134.     stat(filename,&stats);
  135.     if (!S_ISREG(stats.st_mode)){
  136.     NXRunAlertPanel("Can't Process File",
  137.             "%s is not a regular file left unchanged",
  138.             "Okay",NULL,NULL,filename);
  139.     return self;
  140.     }
  141.     buffer_put(filename,&buffer);
  142.     return self;
  143. }
  144.  
  145. - addDirectory: (char *)dirname;
  146. {
  147.     int cc, fd;
  148.     char dirbuf[8*MAXPATHLEN];
  149.     struct direct *dp;
  150.     long basep;
  151.     char *buf;
  152.     char tempbuff[MAXPATHLEN];
  153.     struct stat stats;
  154.  
  155.     stat(dirname,&stats);
  156.     if (S_ISDIR(stats.st_mode) && (access(dirname,(W_OK|R_OK)|X_OK) == 0)){ /* Check if a dir and W,R,X okay */
  157.     if ((fd = open(dirname, O_RDONLY, 0644)) > 0) {
  158.         cc = getdirentries(fd, (buf = dirbuf), 8*MAXPATHLEN, &basep);
  159.         while (cc) {
  160.         dp = (struct direct *)buf;
  161.         sprintf(tempbuff,"%s/%s",dirname,dp->d_name);
  162.         stat(tempbuff,&stats);
  163.         if (S_ISDIR(stats.st_mode) && is_not_dot_or_dotdot(tempbuff)){
  164.             [self addDirectory:tempbuff];
  165.         }
  166.         if (!S_ISDIR(stats.st_mode) && (access(tempbuff,R_OK|F_OK) == 0) && !access(dirname,W_OK) 
  167.                                                                               && S_ISREG(stats.st_mode)){
  168.             buffer_put(tempbuff,&buffer);                 
  169.         }
  170.         buf += dp->d_reclen;
  171.         if (buf >= dirbuf + cc) {
  172.             cc = getdirentries(fd, (buf = dirbuf), 8*MAXPATHLEN, &basep);
  173.         }
  174.         } /* while (cc) */
  175.         close(fd);
  176.     }
  177.     } 
  178.     return self;
  179. }
  180.  
  181. /* Taken from GNU fileutils v3.1 (ls.c) 
  182.  * Return non-zero if `name' doesn't end in `.' or `..'
  183.  * This is so we don't try to recurse on `././././. ...' 
  184.  */
  185.  
  186. int is_not_dot_or_dotdot (char *name)
  187. {
  188.   char *t;
  189.  
  190.   t = rindex (name, '/');
  191.   if (t)
  192.     name = t + 1;
  193.  
  194.   if (name[0] == '.'
  195.       && (name[1] == '\0'
  196.           || (name[1] == '.' && name[2] == '\0')))
  197.     return 0;
  198.  
  199.   return 1;
  200. }
  201.  
  202.  
  203. - (BOOL)backgroundjobs
  204. {
  205.     if ((buffer.count > 0) || (current_file[0] != '\000')){
  206.     return YES;
  207.     }else{
  208.     return NO;
  209.     }
  210. }
  211.  
  212. - killBackground:sender
  213. {
  214.  
  215.     char *suffix = rindex(current_file,'.');
  216.  
  217.     if (strcmp(suffix,".F")){        // i can rewite this global because the
  218.     strcat(current_file,".F");   // The program will be exited and the current_file
  219.     }else{                           // variable will never be looked at again.
  220.     *suffix='\000';
  221.     }
  222.  
  223.     if (unlink(current_file) < 0){
  224.     perror("unlink");
  225.     }
  226.     return self;
  227. }
  228.  
  229. - update:sender
  230. {
  231.     static int count;
  232.  
  233.     if ( buffer_count != buffer.count ){
  234.     buffer_count = buffer.count;
  235.     [window disableDisplay];
  236.     [browser loadColumnZero];
  237.     [browser displayAllColumns];
  238.     [window reenableDisplay];
  239.     [window display];
  240.     }
  241.  
  242.     if (current_file[0] == '\000'){
  243.     if (count == 0){
  244.         [textfield setTextGray:0.3333333];
  245.         [textfield setStringValue:"No Background Processes"];
  246.         [procfield setStringValue:NULL];
  247.         [circSlider setIntValue:360];
  248.         count = 1;
  249.     }
  250.     }else{
  251.     [textfield setTextGray:0];
  252.     [textfield setStringValue:basename(current_file)];
  253.     [procfield setStringValue:current_process];
  254.     [circSlider setIntValue:( (percent_done < 10) ? 0 : percent_done - 10)];
  255.     count = 0;
  256.     }
  257.     return self;
  258. }
  259.  
  260. /* BROWSER DELEGATE METHODS */
  261. - browser:sender loadCell:cell atRow:(int)row inColumn:(int)column
  262. // Load a specific Value in cell at row,column
  263. {
  264.     
  265.     int buffer_index = (row+buffer.end) % BUFFER_SIZE;
  266.  
  267.     [cell setStringValueNoCopy:buffer.buf[buffer_index]];
  268.     [cell setLeaf:YES];
  269.     return self;
  270. }
  271.  
  272. - (int)browser:sender getNumRowsInColumn:(int)column
  273. // return Number of rows in column 
  274. {
  275.     return buffer.count;
  276. }
  277.  
  278.  
  279. /* WINDOW DELEGATE METHODS */
  280. - windowWillResize:sender toSize:(NXSize *)frameSize
  281. {
  282.     frameSize->width  = MAX(frameSize->width,343.0);
  283.     frameSize->width  = MIN(frameSize->width,500.0);
  284.     frameSize->height = MAX(frameSize->height,258.0);
  285.     return self;
  286. }
  287.  
  288. @end
  289.